﻿using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Documents;
using System.Windows.Shapes;
using System.Windows.Media.Media3D;
using System.Xml;
using System.Windows.Forms;
using System.Collections;
using DWORD = System.UInt32;
using System.ComponentModel;
using System.Data;
using System.Text.RegularExpressions;
using System.Diagnostics;
using Data;
using Layer;
using System.Threading;
using _3DTools;
using System.Runtime.InteropServices;
using ReadBinary;
using Control;
using MicroTimer;

namespace DCSElab_Project
{



    public partial class Main
    {
        #region define attributes

        // define width and height of panel
        const int TOP_ROW = 130;
        const int BOTTON_ROW = 20;

        const int LEFT_COLUM = 100;
        const int RIGHT_COLUM = 100;
        const int CONST_ROUND = 6;

        public System.Windows.Forms.Timer timer;
        
        string path_file;
        cls_Machine machine;

        MicroTimer.MicroTimer microTimerPosition = new MicroTimer.MicroTimer();
        MicroTimer.MicroTimer microTimerMachine = new MicroTimer.MicroTimer();
        StreamReader readSLC;
        double x1=0, x2=0, y1=0, y2=0, z1=0, z2=0;

        ///////////////////////////////////////////////////////////////////////
        Transform3DGroup model_transform;
        Transform3DGroup axis_transfom;


        public Point3D Center;
        ///////////////////////////////////////////////////////////////////////
        int x = 0, hit = -1;

        bool isRead;
        //Model3DGroup solid = new Model3DGroup();// chứa các đối tượng được đọc từ file
        ModelVisual3D model;
        Model3DGroup axes;//chua 3 truc toa do
        ModelVisual3D axis;// chua he truc de hien thi



        Data.Model3D Group;
        ///////////////////////////////////////////////////////////////////////
        ///For transform.

        private bool mDown;
        private Point mLastPos;
        /////////////////////////////////////////////////////////////////////
        // for Slicing.
        Layer.LayerSlicing slice;
        bool isCut;
        Double thickness, grid_distance, x_lenght, y_lenght;
        bool isExport;
        string slcFilePath;// Bien luu duong dan cua file SLC
        public System.Windows.Forms.Timer timerExport;
        /////////////////////////////////////////////////////////////////////
        /// <summary>
        Matrix3D transform_matrix;
        Transform3DGroup trans_model;

        Thread sliceViewerThread;

        #endregion define attributes

        private delegate void UpdateProgressBarDelegate(System.Windows.DependencyProperty dp, Object value);
        


        public Main()
        {
            
            InitializeComponents();
           
        }

        public void InitializeComponents()
        {
            this.InitializeComponent();
            model_transform = new Transform3DGroup();
            axis_transfom = new Transform3DGroup();
            model = new ModelVisual3D();
            axes = new Model3DGroup();
            axis = new ModelVisual3D();
            trans_model = new Transform3DGroup();
            transform_matrix = new Matrix3D();
            slice = new Layer.LayerSlicing();
            path_file = string.Empty;
            thickness = 0;
            grid_distance = 0;
            x = 0; hit = -1;
            Group = new Data.Model3D();
            //set size for Main class
            System.Drawing.Rectangle rect = Screen.PrimaryScreen.WorkingArea;
            this.Height = Screen.PrimaryScreen.WorkingArea.Height;
            this.Width = Screen.PrimaryScreen.WorkingArea.Width;
            grid.Width = this.Width;
            grid.Height = this.Height - 50;

            top_row.MaxHeight = TOP_ROW + 10;
            botton_row.MaxHeight = BOTTON_ROW;
            main_row.MaxHeight = this.Height - TOP_ROW - BOTTON_ROW;


            left_col.MaxWidth = LEFT_COLUM;
            right_col.MaxWidth = RIGHT_COLUM;
            main_col.MaxWidth = this.Width - LEFT_COLUM - RIGHT_COLUM;

            ribbon.Width = this.Width;

            main_viewport.Width = this.Width - LEFT_COLUM - RIGHT_COLUM;
            main_viewport.Height = this.Height - TOP_ROW - BOTTON_ROW;


            //// Cai dat thuoc tinh cho grid chua cac control :Ribbon menu, main_viewport....

            // for display of solid object
            //model.Transform = model_transform;
            model.Transform = new Transform3DGroup();
            main_viewport.Children.Add(model);

            //For display of axes system.
            axis_main_viewport.Children.Add(axis);
            axes = DCSElab_Project.Utility.read_file("axis.stl");
            axes.Children.Add(DCSElab_Project.Utility.Text_Axis());
            axis.Content = axes;
            axis.Transform = new Transform3DGroup();
            camera_axis.Width = camera_axis.Width / 2;
         
            /////////////////////////////////////////////////////
            main_canvas.Focus();
            /////////////////////////////////////////////////////
            Center = new Point3D(0, 0, 0);
            isRead = false;
            isCut = false; // bien kiem tra xem da thuc hien cat hay chua 
            isExport = false;// bien kiem tra xem co du lieu de export file SLC
            slcFilePath = string.Empty;
            //////////////////////////////////////////////////

            timer = new System.Windows.Forms.Timer();
            timer.Interval = 1;
            timer.Tick += new EventHandler(timer_Tick);

            timerExport = new System.Windows.Forms.Timer();
            timerExport.Interval = 1;
            timerExport.Tick += new EventHandler(timerExport_Tick);
        }
        void timerExport_Tick(object sender, EventArgs e)
        {
            progressBar1.Value = progressBar1.Value + 1;
            if (progressBar1.Value >= 100)
            {
                timer.Stop();
                progressBar1.Visibility = Visibility.Hidden;
                progressBar1.Value = 0;
                resultLabel.Visibility = Visibility.Hidden;
            }
            if (progressBar1.Value == 80)
            {
                if (isExport)
                {
                    ExportFile(slcFilePath);
                }
            }
        }

        void timer_Tick(object sender, EventArgs e)
        {
            progressBar1.Value = progressBar1.Value + 1;
            if (progressBar1.Value >= 100)
            {
                timer.Stop();
                progressBar1.Visibility = Visibility.Hidden;
                progressBar1.Value = 0;
                resultLabel.Visibility = Visibility.Hidden;
            }
            if (progressBar1.Value == 80)
            {
                if (isCut)//
                {
                    slice.CreateData(Group, thickness, grid_distance,x_lenght,y_lenght);

                }
                else
                {
                    Mesh3D mesh = Read_STL_File(path_file);
                    if (mesh.GetTriangleNumber() >= 1)
                    {
                        Group.list_mesh3D.Add(mesh);// after reading file, add model to group.
                        x++;
                        Center = Group.GetCenter();
                        isRead = true;
                        Utility.SetCamera(camera, Group);
                        Debug.WriteLine("Number of model" + x.ToString());
                        model.Children.Add(Group.list_mesh3D[x - 1].CreateModel3D(Colors.Aquamarine));
                        resultLabel.Visibility = Visibility.Visible;
                    }
                    else
                    {
                      System.Windows.Forms.MessageBox.Show("Failed to read file", "File Reading", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Error);
                    }
                }

            }

        }


        private void Show_Open(object target, ExecutedRoutedEventArgs args)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.InitialDirectory = "c:\\";
            openFileDialog1.Filter = "STL files (*.stl)|*.stl|All files (*.*)|*.*";
            openFileDialog1.Title = "Open";
            openFileDialog1.FilterIndex = 2;
            openFileDialog1.RestoreDirectory = true;
            //////////////////

            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                path_file = openFileDialog1.FileName;

                progressBar1.Visibility = Visibility.Visible;
                timer.Start();

            }


        }

        public Mesh3D Read_STL_File(string file_path)
        {
      
            Mesh3D mesh = new Mesh3D();
            Vector3D normal = new Vector3D();
            Point3D v1 = new Point3D();
            Point3D v2 = new Point3D();
            Point3D v3 = new Point3D();
            bool isBinaryFile = Utility.IsBinaryFile(file_path, 10240);

            if (!isBinaryFile)
            {
                int dem = 0;
                string s, s1;
                string[] separators = new string[] { " ", "," };
                StreamReader re = System.IO.File.OpenText(file_path);
                while ((s1 = re.ReadLine()) != null)
                {
                    s = s1.Trim();
                    s.ToLower();
                    s = DCSElab_Project.Utility.ChuanHoa(s);
                    string[] line;

                    if (s.StartsWith("solid"))
                    {
                        //do something

                        continue;
                    }

                    if (s.StartsWith("facet"))// gap tu khoa facet thi xac dinh dinh cua phap vecto
                    {

                        string[] slipt = s.Split(new Char[] { ' ' });

                        normal = new Vector3D(Double.Parse(slipt[2]), Double.Parse(slipt[3]), Double.Parse(slipt[4]));
                    }
                    else if (s.StartsWith("vertex"))
                    {
                        // parse: vertex x y z  
                        if (dem == 0)
                        {
                            line = s.Split(' ');
                            v1 = new Point3D(Double.Parse(line[1]), Double.Parse(line[2]), Double.Parse(line[3]));
                            dem++;
                        }
                        else if (dem == 1)
                        {
                            line = s.Split(' ');
                            v2 = new Point3D(Double.Parse(line[1]), Double.Parse(line[2]), Double.Parse(line[3]));
                            dem++;
                        }
                        else
                        {
                            line = s.Split(' ');
                            v3 = new Point3D(Double.Parse(line[1]),Double.Parse(line[2]),Double.Parse(line[3]));
                            dem = 0;
                        }
                    }
                    else if (s == "endfacet")
                    {
                        
                        Triangle3D tri = new Triangle3D(normal, v1, v2, v3);// Create Triangle from reading file.
                        mesh.list_triangle.Add(tri);// add triangle to mesh.
                        isRead = false;
                        Debug.WriteLine(v1.ToString());
                        Debug.WriteLine(v2.ToString());
                        Debug.WriteLine(v3.ToString());
                        Debug.WriteLine("--------------------------------");
                    }
                    else if (s.StartsWith("endsolid"))
                    {

                    }

                }
            }
            else
            {
                byte[] _data;
                _data = System.IO.File.ReadAllBytes(file_path);

                STL_BinaryParser binarySTL = new STL_BinaryParser(_data);
                binarySTL.getSizeFile();

                const int INDEX_VERTEX0 = 0;
                const int INDEX_VERTEX1 = 1;
                const int INDEX_VERTEX2 = 2;
                const int INDEX_NORMAL = 3;

                for (int k = 0; k < binarySTL.numTriangles; k++)
                {
                    ArrayList collection = binarySTL.index(k);
                    normal = (Vector3D)collection[INDEX_NORMAL];
                    v1 = (Point3D)collection[INDEX_VERTEX0];
                    v2 = (Point3D)collection[INDEX_VERTEX1];
                    v3 = (Point3D)collection[INDEX_VERTEX2];

                    Triangle3D tri = new Triangle3D(normal, v1, v2, v3);// Create Triangle from reading file.
                    mesh.list_triangle.Add(tri);// add triangle to mesh.
                    Debug.WriteLine("Ver1: "+v1.ToString());
                    Debug.WriteLine("Ver2: " + v2.ToString());
                    Debug.WriteLine("Ver3: " + v3.ToString());
                    Debug.WriteLine("--------------------------------");
                }
            }
             return mesh;
            
        }
      void ExportFile(string filePath)
        {
           
          try
            {
                StreamWriter file = new StreamWriter(filePath);
                Point3D point = new Point3D();
                Double zt = -100;
                Double Z = 0;
                Double X_Write, Y_Write, Z_Write;
                if (slice.final3D_list.Count > 0)
                {
                    for (int i = 0; i < slice.final3D_list.Count; i++)
                    {
                        Debug.WriteLine("i = {0}", i);
                        point = slice.final3D_list[i];
                        Z = point.Z;
                        X_Write = Math.Round(point.X, CONST_ROUND);
                        Y_Write = Math.Round(point.Y, CONST_ROUND);
                        Z_Write = Math.Round(point.Z, CONST_ROUND);
                        if (zt != Z)
                        {

                            Debug.WriteLine("Start new slice at Z = {0}", Z);
                            file.WriteLine("Z\t" + Z_Write);
                            if (point.X == -8888)
                            {
                                file.WriteLine("E");
                            }
                            else if (point.X == -1111)
                            {
                                file.WriteLine("L");
                            }
                            else
                            {
                                file.WriteLine(X_Write + "\t\t" + Y_Write);
                            }
                            zt = point.Z;
                            Debug.WriteLine("x = {0} y= {1}", X_Write, Y_Write);

                        }
                        else
                        {

                            if (point.X == -8888)
                            {
                                file.WriteLine("E");
                            }
                            else if (point.X == -1111)
                            {
                                file.WriteLine("L");
                            }
                            else
                            {
                                file.WriteLine(X_Write + "\t\t" + Y_Write);
                            }
                            Debug.WriteLine("x = {0} y= {1}", X_Write, Y_Write);
                        }
                    }
                    file.Close();
                    isCut = false;
                }
                else System.Windows.Forms.MessageBox.Show("No Data to export");
            }
            catch { System.Windows.Forms.MessageBox.Show("Operation failed"); }
        }
       private void button1_Click(object sender, RoutedEventArgs e)
        {

            List<Point3D> temp = new List<Point3D>();
            List<Point3D> line = new List<Point3D>();
            line.Add(new Point3D(1, 2, 0));
            line.Add(new Point3D(3, 4, 0));
            line.Add(new Point3D(5, 5, 0));
            line.Add(new Point3D(8, 3, 0));
            line.Add(new Point3D(5, 1, 0));
            line.Add(new Point3D(3, 0, 0));
            temp = InsertDetectPoint(line, new Point3D(1111,1111,1111));
        }

       public List<Point3D> InsertDetectPoint(List<Point3D> a, Point3D p)
       {
           List<Point3D> temp = new List<Point3D>();
           temp.Add(p);
           for (int i = 0; i < a.Count; i++)
           {
               temp.Add(a[i]);
               temp.Add(p);
           }
           temp.RemoveAt(temp.Count - 1);
           return temp;
       }

        /************************************************************************************/
        private void Grid_MouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
        {
            if (isRead == true)
            {

                camera.Width = camera.Width - e.Delta * 3.5 / 250D;

            }




        }
        private void Grid_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {

            if (mDown == true && isRead == true)
            {
                Point pos = Mouse.GetPosition(main_viewport);
                Point actualPos = new Point(pos.X - main_viewport.ActualWidth / 2, main_viewport.ActualHeight / 2 - pos.Y);
                Double dx = actualPos.X - mLastPos.X, dy = actualPos.Y - mLastPos.Y;

                Double mouseAngle = 0;
                if (dx != 0 && dy != 0)
                {
                    mouseAngle = Math.Asin(Math.Abs(dy) / Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2)));
                    if (dx < 0 && dy > 0) mouseAngle += Math.PI / 2;
                    else if (dx < 0 && dy < 0) mouseAngle += Math.PI;
                    else if (dx > 0 && dy < 0) mouseAngle += Math.PI * 1.5;
                }
                else if (dx == 0 && dy != 0) mouseAngle = Math.Sign(dy) > 0 ? Math.PI / 2 : Math.PI * 1.5;
                else if (dx != 0 && dy == 0) mouseAngle = Math.Sign(dx) > 0 ? 0 : Math.PI;

                Double axisAngle = mouseAngle + Math.PI / 2;

                Vector3D truc = new Vector3D(Math.Cos(axisAngle) * 4, Math.Sin(axisAngle) * 4, 0);

                Double rotation = 0.01 * Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2));
                ///////////////////////////////////////////////////////////////////////
                Transform3DGroup trans_axis = axis.Transform as Transform3DGroup;
                Transform3DGroup trans_model = model.Transform as Transform3DGroup;

                // notich this to create rotation matrix for slicing.      
                QuaternionRotation3D r_model = new QuaternionRotation3D(new Quaternion(truc, rotation * 180 / Math.PI));
                //////////////////////////////////////////////////////////////////
                // For solid model rotation
                RotateTransform3D rotate_model = new RotateTransform3D(r_model);
                rotate_model.CenterX = Center.X;
                rotate_model.CenterY = Center.Y;
                rotate_model.CenterZ = Center.Z;
                trans_model.Children.Add(rotate_model);

                ///////////////////////////////////////////////////////////////////
                //For three axes 
                RotateTransform3D rotate_axis = new RotateTransform3D(r_model);
                rotate_axis.CenterX = 0;
                rotate_axis.CenterY = 0;
                rotate_axis.CenterZ = 0;
                trans_axis.Children.Add(rotate_axis);

                ///////////////////////////////////////////////////////////////////
                mLastPos = actualPos;
            }
        }
        private void Grid_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (e.LeftButton != MouseButtonState.Pressed) return;
            mDown = true;
            Point pos = Mouse.GetPosition(main_viewport);
            mLastPos = new Point(pos.X - main_viewport.ActualWidth / 2, main_viewport.ActualHeight / 2 - pos.Y);


        }
        private void Grid_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            mDown = false;
        }
        private HitTestResultBehavior HTResult(System.Windows.Media.HitTestResult rawresult)
        {
            RayHitTestResult rayResult = rawresult as RayHitTestResult;

            //  assign event for each of object
            if (rayResult != null)
            {
                if (Group.list_mesh3D.Count > 0)
                {
                    for (int i = 0; i < model.Children.Count; i++)
                    {
                        if (rayResult.ModelHit == Group.list_mesh3D[i].geometry)
                        {
                            hit = i;// hit will be assigned value when 3d model was hit.
                            SolidColorBrush brush = new SolidColorBrush();
                            brush.Color = Colors.LightGoldenrodYellow;
                            Group.list_mesh3D[i].geometry.Material = new DiffuseMaterial(brush);
                        }
                    }
                }
            }
            return HitTestResultBehavior.Stop;
        }

        private void main_canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            //for hit testing

            System.Windows.Point mouseposition = e.GetPosition(main_canvas);
            Point3D testpoint3D = new Point3D(mouseposition.X, mouseposition.Y, 0);
            Vector3D testdirection = new Vector3D(mouseposition.X, mouseposition.Y, 10);
            PointHitTestParameters pointparams = new PointHitTestParameters(mouseposition);
            RayHitTestParameters rayparams = new RayHitTestParameters(testpoint3D, testdirection);
            VisualTreeHelper.HitTest(main_viewport, null, HTResult, pointparams);
            Keyboard.Focus(main_canvas);
        }



        //private void Show_Save(object target, ExecutedRoutedEventArgs args)
        //{
        //    if (isCut == true)
        //    {
        //        Microsoft.Win32.SaveFileDialog save = new Microsoft.Win32.SaveFileDialog();

        //        save.FileName = "DCSELAB";
        //        save.AddExtension = true;
        //        save.DefaultExt = "slc";
        //        save.Filter = "SLC File(*.SLC)|*.slc|All files (*.*)|*.*";
        //        if (save.ShowDialog() == true)
        //        {

        //            if (save.FilterIndex == 1)
        //            {
                   
        //                slcFilePath = save.FileName;
        //                progressBar1.Visibility = Visibility.Visible;
        //                timerExport.Start();
        //            }
        //        }
        //    }
        //    else
        //    {
        //        System.Windows.Forms.MessageBox.Show(" No Data to export");
        //    }

        //}
        private void Show_Save(object target, ExecutedRoutedEventArgs args)
        {
            if (isCut == true)
            {
                Microsoft.Win32.SaveFileDialog save = new Microsoft.Win32.SaveFileDialog();

                save.FileName = "DCSELAB";
                save.AddExtension = true;
                save.DefaultExt = "slc";
                save.Filter = "SLC File(*.SLC)|*.slc|All files (*.*)|*.*";
                if (save.ShowDialog() == true)
                {

                    if (save.FilterIndex == 1)
                    {
                        try
                        {
                            StreamWriter file = new StreamWriter(save.FileName);
                            Point3D point = new Point3D();
                            Double zt = -100;
                            Double Z = 0;
                            Double X_Write, Y_Write, Z_Write;
                            if (slice.final3D_list.Count > 0)
                            {
                                for (int i = 0; i < slice.final3D_list.Count; i++)
                                {
                                    Debug.WriteLine("i = {0}", i);
                                    point = slice.final3D_list[i];
                                    Z = point.Z;
                                    X_Write = Math.Round(point.X, CONST_ROUND);
                                    Y_Write = Math.Round(point.Y, CONST_ROUND);
                                    Z_Write = Math.Round(point.Z, CONST_ROUND);
                                    if (zt != Z)
                                    {

                                        Debug.WriteLine("Start new slice at Z = {0}", Z);
                                        file.WriteLine("Z\t" + Z_Write);
                                        if (point.X == -8888)
                                        {
                                            file.WriteLine("E");
                                        }
                                        else if (point.X == -1111)
                                        {
                                            file.WriteLine("L");
                                        }
                                        else
                                        {
                                            file.WriteLine(X_Write + "\t\t" + Y_Write);
                                        }
                                        zt = point.Z;
                                        Debug.WriteLine("x = {0} y= {1}", X_Write, Y_Write);

                                    }
                                    else
                                    {

                                        if (point.X == -8888)
                                        {
                                            file.WriteLine("E");
                                        }
                                        else if (point.X == -1111)
                                        {
                                            file.WriteLine("L");
                                        }
                                        else
                                        {
                                            file.WriteLine(X_Write + "\t\t" + Y_Write);
                                        }
                                        Debug.WriteLine("x = {0} y= {1}", X_Write, Y_Write);
                                    }
                                }
                                file.Close();
                                isCut = false;
                            }
                            else System.Windows.Forms.MessageBox.Show("No Data to export");
                        }
                        catch { System.Windows.Forms.MessageBox.Show("Operation failed"); }
                    }
                }
            }
            else
            {
                System.Windows.Forms.MessageBox.Show(" No Data to export");
            }

        }
        private void Show_New(object target, ExecutedRoutedEventArgs args)
        {
            if (isRead)
            {
                try
                {
                    progressBar1.Visibility = Visibility.Hidden;
                    // solid.Children.Clear();
                    model.Children.Clear();

                    Group.list_mesh3D.Clear();
                    Group = new Data.Model3D();
                    camera.Position = new Point3D(0, 0, 10);
                    Center = new Point3D(0, 0, 0);
                    isRead = false;
                    isCut = false;
                    isExport = false;
                    axis.Transform = new Transform3DGroup();
                    model.Transform = new Transform3DGroup();
                    for (int i = 0; i < model.Children.Count; i++)
                    {
                        model.Children.RemoveAt(i);
                    }
                    thickness = 0;
                    grid_distance = 0;
                    x = 0; hit = -1;
                    Group = new Data.Model3D();
                    
                }
                catch { }
            }
        }
        private void Show_Rotate(object target, ExecutedRoutedEventArgs args)
        {

            Mesh3D me = new Mesh3D();


            if (hit >= 0)
            {
                // retrieve name from listbox

                Rotate_dialog dlg = new Rotate_dialog();
                RotateTransform3D rotate = new RotateTransform3D();
                dlg.ShowDialog();
                if (dlg.DialogResult == true)
                {

                    rotate = rotate_update(dlg.truc_quay, dlg.goc_quay);
                    Group.list_mesh3D[hit].Transfoms(transform_matrix);
                    trans_model.Children.Add(rotate);
                    model.Children[hit].Transform = trans_model;
                    Double maxz = Group.Zmax();

                    hit = -1;

                }
            }
            else System.Windows.Forms.MessageBox.Show("Please choose item on main_viewport");

        }

        private RotateTransform3D rotate_update(int l, Double goc)
        {

            QuaternionRotation3D r_model = new QuaternionRotation3D();
            Matrix3D m = new Matrix3D();
            switch (l)
            {

                case 0:
                    m.Rotate(new Quaternion(new Vector3D(1, 0, 0), goc));
                    r_model = new QuaternionRotation3D(new Quaternion(new Vector3D(1, 0, 0), goc));
                    break;
                case 1:
                    m.Rotate(new Quaternion(new Vector3D(0, 1, 0), goc));
                    r_model = new QuaternionRotation3D(new Quaternion(new Vector3D(0, 1, 0), goc));
                    break;
                case 2:
                    m.Rotate(new Quaternion(new Vector3D(0, 0, 1), goc));
                    r_model = new QuaternionRotation3D(new Quaternion(new Vector3D(0, 0, 1), goc));
                    break;
            }
            transform_matrix = Matrix3D.Multiply(transform_matrix, m);
            RotateTransform3D rotate_model = new RotateTransform3D(r_model);
            rotate_model.CenterX = Center.X;
            rotate_model.CenterY = Center.Y;
            rotate_model.CenterZ = Center.Z;
            return rotate_model;
        }
        private void Show_Mirror(object target, ExecutedRoutedEventArgs args)
        {

            Mesh3D me = new Mesh3D();
            if (hit >= 0)// khi user da hit
            {

                Mirror_dialog dlg = new Mirror_dialog();
                MatrixTransform3D ma = new MatrixTransform3D();

                me = Group.GetModel(hit);
                dlg.ShowDialog();
                if (dlg.DialogResult == true) // khi user chap nhan
                {

                    mirror_object(dlg.truc_doixung);// tao ma tran tu cac thiet lap cua user
                    x++;
                    Group.list_mesh3D.Add(me);// them doi tuong vao danh sach
                    model.Children.Add(me.CreateModel3D(Colors.Red));
                    trans_model.Children.Add(mirror_object(dlg.truc_doixung));
                    // thuc hien transform
                    Group.list_mesh3D[x - 1].transform(ma.Matrix);
                    model.Children[x - 1].Transform = trans_model;

                    hit = -1;

                }

            }
            else System.Windows.Forms.MessageBox.Show("Please choose item on main_viewport");
        }
        private MatrixTransform3D mirror_object(int k)
        {
            Matrix3D m = new Matrix3D();
            switch (k)
            {
                case 0:
                    m = new Matrix3D(-1, 0, 0, 0,
                                   0, 1, 0, 0,
                                   0, 0, 1, 0,
                                   0, 0, 0, 1);
                    break;
                case 1:
                    m = new Matrix3D(1, 0, 0, 0,
                                     0, -1, 0, 0,
                                     0, 0, 1, 0,
                                     0, 0, 0, 1);
                    break;
                case 2:
                    m = new Matrix3D(1, 0, 0, 0,
                                     0, 1, 0, 0,
                                     0, 0, -1, 0,
                                     0, 0, 0, 1);
                    break;

            }
            transform_matrix = Matrix3D.Multiply(transform_matrix, m);
            MatrixTransform3D ma = new MatrixTransform3D();
            ma.Matrix = m;
            return ma;

        }
        private void Show_Select(object target, ExecutedRoutedEventArgs args)// for Movement Function
        {

            Mesh3D me = new Mesh3D();
            if (hit >= 0)
            {

                Move_Dialoge dlg = new Move_Dialoge();
                TranslateTransform3D pan = new TranslateTransform3D();
                dlg.ShowDialog();
                if (dlg.DialogResult == true)
                {
                    pan = move_object(dlg.x, dlg.y, dlg.z);
                    Group.list_mesh3D[hit].Transfoms(transform_matrix);
                    trans_model.Children.Add(pan);
                    model.Children[hit].Transform = trans_model;
                    hit = -1;


                }
            }
            else System.Windows.Forms.MessageBox.Show("Please choose item on main_viewport");

        }
        private TranslateTransform3D move_object(Double x, Double y, Double z)
        {
            Matrix3D m = new Matrix3D();
            m.Translate(new Vector3D(x, y, z));
            transform_matrix = Matrix3D.Multiply(transform_matrix, m);
            TranslateTransform3D pan = new TranslateTransform3D();
            pan.OffsetX = x;
            pan.OffsetY = y;
            pan.OffsetZ = z;
            return pan;
        }

        private void Show_Scale(object target, ExecutedRoutedEventArgs args)
        {

            Mesh3D me = new Mesh3D();
            if (hit >= 0)
            {

                Scale_dialog dlg = new Scale_dialog();
                ScaleTransform3D scal_trans = new ScaleTransform3D();
                dlg.ShowDialog();
                if (dlg.DialogResult == true)
                {
                    scal_trans = scale_object(dlg.x, dlg.y, dlg.z);
                    Group.GetModel(hit).Transfoms(transform_matrix);
                    trans_model.Children.Add(scal_trans);
                    model.Children[hit].Transform = trans_model;
                    hit = -1;
                }


            }
            else System.Windows.Forms.MessageBox.Show("Please choose item on main_viewport");
        }
        private ScaleTransform3D scale_object(Double x, Double y, Double z)
        {
            Matrix3D m = new Matrix3D();
            m.Scale(new Vector3D(x, y, z));
            transform_matrix = Matrix3D.Multiply(transform_matrix, m);
            ScaleTransform3D scale = new ScaleTransform3D();
            scale.ScaleX = x;
            scale.ScaleY = y;
            scale.ScaleZ = z;
            scale.CenterX = Center.X;
            scale.CenterY = Center.Y;
            scale.CenterZ = Center.Z;
            return scale;
        }
        private void Show_Duplicate(object sender, ExecutedRoutedEventArgs e)// Duplication fucntion.
        {


            Mesh3D mesh = new Mesh3D();
            if (hit >= 0)
            {

                mesh = Group.list_mesh3D[hit];
                Group.list_mesh3D.Add(mesh);
                model.Children.Add(mesh.CreateModel3D(Colors.Aquamarine));
                hit = -1;
            }
            else System.Windows.Forms.MessageBox.Show("Please choose item on main_viewport");
        }

        private void Show_Top(object target, ExecutedRoutedEventArgs args) //Model information 
        {
            if (isRead)
            {
                //RotateTransform3D rotate = new RotateTransform3D();
                //rotate = rotate_update(0, 90);
                //trans_model.Children.Add(rotate);
                //model.Transform = trans_model;

                axis.Transform = new Transform3DGroup();
                model.Transform = new Transform3DGroup();
                trans_model = new Transform3DGroup();
                RotateTransform3D rotate = new RotateTransform3D();
                rotate = rotate_update(0, 90);
                trans_model.Children.Add(rotate);
                model.Transform = trans_model;
                Transform3DGroup trans_axis = axis.Transform as Transform3DGroup;
                RotateTransform3D rotate_axis = rotate;
                rotate_axis.CenterX = 0;
                rotate_axis.CenterY = 0;
                rotate_axis.CenterZ = 0;
                trans_axis.Children.Add(rotate_axis);
            }

        }
        private void Show_Botton(object target, ExecutedRoutedEventArgs args) //Model information 
        {
            if (isRead)
            {
                RotateTransform3D rotate = new RotateTransform3D();
                rotate = rotate_update(0, -90);
                trans_model.Children.Add(rotate);
                model.Transform = trans_model;
            }

        }
        private void Show_Right(object target, ExecutedRoutedEventArgs args) //Model information 
        {
            if (isRead)
            {
                //RotateTransform3D rotate = new RotateTransform3D();
                //rotate = rotate_update(1, 90);
                //trans_model.Children.Add(rotate);
                //model.Transform = trans_model;

                axis.Transform = new Transform3DGroup();
                model.Transform = new Transform3DGroup();
                trans_model = new Transform3DGroup();
                RotateTransform3D rotate = new RotateTransform3D();
                rotate = rotate_update(1, 90);
                trans_model.Children.Add(rotate);
                model.Transform = trans_model;
                Transform3DGroup trans_axis = axis.Transform as Transform3DGroup;
                RotateTransform3D rotate_axis = rotate;
                rotate_axis.CenterX = 0;
                rotate_axis.CenterY = 0;
                rotate_axis.CenterZ = 0;
                trans_axis.Children.Add(rotate_axis);
                
            }
        }

         private void Show_Left(object target, ExecutedRoutedEventArgs args) //Model information 
        {
            if (isRead)
            {
                //RotateTransform3D rotate = new RotateTransform3D();
                //rotate = rotate_update(1, -90);
                //trans_model.Children.Add(rotate);
                //model.Transform = trans_model;

                axis.Transform = new Transform3DGroup();
                model.Transform = new Transform3DGroup();
                trans_model = new Transform3DGroup();
                RotateTransform3D rotate = new RotateTransform3D();
                rotate = rotate_update(1, -90);
                trans_model.Children.Add(rotate);
                model.Transform = trans_model;
                Transform3DGroup trans_axis = axis.Transform as Transform3DGroup;
                RotateTransform3D rotate_axis = rotate;
                rotate_axis.CenterX = 0;
                rotate_axis.CenterY = 0;
                rotate_axis.CenterZ = 0;
                trans_axis.Children.Add(rotate_axis);
            }

        }
         private void Show_Frame(object target, ExecutedRoutedEventArgs args) //Model information 
         {
             System.Windows.Forms.MessageBox.Show("Top");

         }
        // Shadow function 
        private void Show_Shadow(object target, ExecutedRoutedEventArgs args)
        {

            Mesh3D me = new Mesh3D();
            if (hit >= 0)
            {

                me = Group.GetModel(hit);

                Group.list_mesh3D.Add(me);

            }
            else System.Windows.Forms.MessageBox.Show("Please choose item from listbox to display info");
        }
        private void Show_Original(object sender, ExecutedRoutedEventArgs e)
        {
            System.Windows.Forms.MessageBox.Show("Orginal");
        }
        private void Show_Scan(object target, ExecutedRoutedEventArgs args)
        {
        }


        private void Show_Auto(object target, ExecutedRoutedEventArgs args)
        {

        }

        private void Show_Config(object target, ExecutedRoutedEventArgs args)
        {

        }
        //for slicing model

        private void Slice_Button_Click(object target, ExecutedRoutedEventArgs args)
        {
           if (isRead) // Thuc hien khi chuong trinh da doc du lieu
            {
                Slice_Dialog slice_dlg = new Slice_Dialog();
                slice_dlg.ShowDialog();
                if (slice_dlg.DialogResult == true)
                {

                    thickness = slice_dlg.Getdz();
                    grid_distance = slice_dlg.Getdm();
                    x_lenght = slice_dlg.Getdx();
                    y_lenght = slice_dlg.Getdy();
                    isCut = true;
                    progressBar1.Visibility = Visibility.Visible;
                    timer.Start();
                    isExport = true;// da thuc hien cat va du lieu san sang cho viec export file SLC

                }
               
            }
            else
            {
                System.Windows.Forms.MessageBox.Show("No data to slice\nPlease open file for slicing");
            }
        }
        private void Triangle_Mesh_Click(object target, ExecutedRoutedEventArgs args)
        {

            System.Windows.Forms.MessageBox.Show("Invalid Command");
        }
        ///// <summary>
        ///// Ham thuc hien cat lop
        ///// </summary>
        ///// <param name="thickness"></param>
        ///// <param name="grid_dis"></param>
        // private void Slice_Function(Double thickness, Double grid_dis)
        // {
        //     slice.CreateData(Group,thickness,grid_dis);

        // }

        private void OnShowQAT(object target, ExecutedRoutedEventArgs args)
        {
            //MessageBox.Show("This is the QAT!", "QAT Dialog");
        }

        private void Exit_Program(object sender, ExecutedRoutedEventArgs e)
        {

        }

        private void Select_Lang_Click(object sender, ExecutedRoutedEventArgs e)
        {
            //MessageBox.Show("Language");
        }
        private void OnCanExecute(object target, CanExecuteRoutedEventArgs args)
        {
            args.CanExecute = true;
        }

        private void list_model_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (Keyboard.IsKeyDown(Key.Delete))
            {

            }
        }


        // process Menu item click
        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {

        }

        private void main_canvas_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {

            if (Keyboard.IsKeyDown(Key.Delete))
            {


                if (hit >= 0)
                {
                    Group.list_mesh3D.RemoveAt(hit);
                    model.Children.RemoveAt(hit);
                    x--;
                }
            }
        }

        private void Show_Export(object sender, ExecutedRoutedEventArgs e)
        {

        }
        private void SliceViewDlg_Click(object target, ExecutedRoutedEventArgs args)
        {
            if (isCut)
            {
                SliceViewDlg slice_dlg = new SliceViewDlg();

                slice_dlg.SetPoint3DList(slice.GetListPoint());
                slice_dlg.SetThickness(thickness);
                slice_dlg.ShowDialog();
            }
            else { System.Windows.Forms.MessageBox.Show("No sliced object to display"); }
        }

        private void ReadFileToRun_Click(object sender, RoutedEventArgs e)
        {
            //ReadFileToRun_Click
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.InitialDirectory = "c:\\";
            openFileDialog1.Filter = "SLC files (*.slc)|*.slc";
            openFileDialog1.Title = "Open";
            openFileDialog1.FilterIndex = 2;
            openFileDialog1.RestoreDirectory = true;
            //////////////////

            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                path_file = openFileDialog1.FileName;
            }
            readSLC = System.IO.File.OpenText(path_file);

        }

        private void InitMachine_Click(object sender, RoutedEventArgs e)
        {
            //InitMachine_Click

            machine = new cls_Machine(9, 10);

            machine.SetupStep();
            machine.SetupServoParameter();
            machine.SetEncoder();

            machine.ServoOn();
            machine.OpenServoSource();

            //timer using for updating XYZ axis
            microTimerPosition.MicroTimerElapsed += new MicroTimer.MicroTimer.MicroTimerElapsedEventHandler(OnTimedEventPosition);
            microTimerPosition.Interval = 5000; // Call micro timer every 1000µs (1ms)
            microTimerPosition.Enabled = true;
            microTimerPosition.Start();

            //timer using for running machine
            microTimerMachine.MicroTimerElapsed += new MicroTimer.MicroTimer.MicroTimerElapsedEventHandler(OnTimedEventMachine);
            microTimerMachine.Interval = 100000; // Call micro timer every 1000µs (1ms)
            microTimerMachine.Enabled = true;
            z1 = z2;
            y1 = y2;
            x1 = x2;
        }
        private void OnTimedEventPosition(object sender, MicroTimer.MicroTimerEventArgs timerEventArgs)
        {
            DWORD x = 0, y = 0, z = 0, temp = 0;
            machine.ReadRealEncoder(temp, x, temp, y, temp, temp, temp, z);
            xAxis.Text = "X: " + x.ToString();
            yAxis.Text = "Y: " + y.ToString();
            zAxis.Text = "Z: " + z.ToString();
        }

        private void OnTimedEventMachine(object sender, MicroTimer.MicroTimerEventArgs timerEventArgs)
        {
            //check status
            if (!machine.busy())
            {
                string s1 = readSLC.ReadLine(), s;
                if (s1 != null)
                {
                    s = s1.Trim();
                    s.ToLower();
                    s = DCSElab_Project.Utility.ChuanHoa(s);
                    string[] line;
                    if (s.StartsWith("Z"))
                    {
                        z1 = z2;
                        machine.ControlKnife(z2 - z1);
                    }
                    else
                    {
                        x1 = x2;
                        y1 = y2;
                        line = s.Split(' ');
                        x2 = Double.Parse(line[1]);
                        y2 = Double.Parse(line[2]);
                        machine.GotoXY(x2 - x1, y2 - y1);
                    }
                }
                else
                {
                    readSLC.Close();
                    microTimerMachine.Stop();
                }
            }
        }

        private void Run_Click(object sender, RoutedEventArgs e)
        {
            //Run_Click
            microTimerMachine.Start();
        }

        private void SetupParameter_Click(object sender, RoutedEventArgs e)
        {
            //SetupParameter_Click
        }

        private void TestCard_Click(object sender, RoutedEventArgs e)
        {
            //TestCard_Click
        }

        private void Stop_Click(object sender, RoutedEventArgs e)
        {
            machine.Stop();
        }
    }
}
